We are migrating the bug tracker to github Issues. This is now the preferred way to report NASM bugs.

Self-registration is disabled due to spam issue (mail gorcunov@gmail.com or hpa@zytor.com to create an account)

Bug 3392923 - (-f obj) Label declared EXTERN, then GLOBAL, then defined leads to error "label ... inconsistently redefined"
Summary: (-f obj) Label declared EXTERN, then GLOBAL, then defined leads to error "lab...
Status: OPEN
Alias: None
Product: NASM
Classification: Unclassified
Component: Assembler (show other bugs)
Version: 2.16.xx
Hardware: All All
: Medium annoyance
Assignee: nobody
URL:
Depends on:
Blocks:
 
Reported: 2024-11-02 10:18 PDT by E. C. Masloch
Modified: 2024-11-04 08:41 PST (History)
5 users (show)

Obtained from: Built from git using configure
Generated by: Human
Bug category: Documentation incorrect, Invalid main output, Unexpected or confusing behavior
Observed for: Invalid input
Regression: ---
Regression since:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description E. C. Masloch 2024-11-02 10:18:08 PDT
This is what the manual says:

https://www.nasm.us/xdoc/2.16.03/html/nasmdoc7.html#section-7.5

> You can declare the same variable as EXTERN
> more than once: NASM will quietly ignore the
> second and later redeclarations.
>
> If a variable is declared both GLOBAL and
> EXTERN, or if it is declared as EXTERN and
> then defined, it will be treated as GLOBAL.
> If a variable is declared both as COMMON
> and EXTERN, it will be treated as COMMON.

From this description I assumed that it is valid to declare a label as extern first, then as global, and finally define it. However, with `-f obj` output format and a label used in this order I get an error.

It seems I can work around this either by using EXTERN *instead* of GLOBAL; multiple EXTERNs and one definition of the label results in the desired output. Using EXTERN then *defining* the label and finally using GLOBAL (*after* the definition) also appears to work. According to omfdump both test2.obj and test4.obj produce exactly the same (and desired) output, modulo the different filename in the object file.

Test cases follow. I expect the same output for all of them but test.asm fails with the error:

test$ nasm -v
NASM version 2.16.02rc2 compiled on Oct 12 2023
test$ cat test.asm
section .text
extern foo
global foo
foo:
test$ cat test2.asm
section .text
extern foo
extern foo
foo:
test$ cat test3.asm
section .text
global foo
foo:
extern foo
test$ cat test4.asm
section .text
extern foo
foo:
global foo
test$ nasm -fobj test.asm
test.asm:4: error: label `foo' inconsistently redefined
test.asm:2: info: label `foo' originally defined here
test$ nasm -fobj test2.asm
test$ nasm -fobj test3.asm
test$ nasm -fobj test4.asm
test$
Comment 1 E. C. Masloch 2024-11-04 08:41:00 PST
In my MS-DOS kernel porting work I came across uses of the IF2 and IFNDEF constructs in the MASM source that try to determine whether EXTRN has to be used or not. This must depend on whether the symbol is defined in the same assembly unit or not. However, it is valid for the use that may require EXTRN to occur during assembling before the spot that defines the symbol. I do not think there is a comprehensive way to do that in NASM. However, the expected outcome of ignoring an EXTERN directive if the symbol is defined during assembly would fit this use case just fine; instead of the IF2/IFNDEF just unconditionally use EXTERN and let NASM sort it out.

After writing this bug report I changed my sources to put the PUBLIC macro call (which preprocesses to a GLOBAL directive) *after* the definition of the symbol. As mentioned this  works around the NASM bug.

Reference: https://hg.pushbx.org/ecm/msdos4/rev/6db48565774f